package curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.TimeUnit;

/**
 * 分布式锁
 * zk实现
 */
public class DistributeLock {

    /**
     * 锁名称
     */
    private String lockName;

    private static String ZK_CONNECT_STRING;
    private static String ZK_ROOT;
    /**
     * zk客户端
     */
    private static CuratorFramework client;

    public static void initClient(String connectString, String root) throws Exception {
        ZK_CONNECT_STRING = connectString;
        ZK_ROOT = root;
        client = CuratorFrameworkFactory.newClient(ZK_CONNECT_STRING,
                new ExponentialBackoffRetry(1000, 3));
        client.start();
    }

    public DistributeLock(String lockName) throws Exception {
        this.lockName = lockName;
    }

    private String getFullLockName() {
        return ZK_ROOT + "/" + lockName;
    }

    public void lock() throws Exception {
        if(client.checkExists().forPath(ZK_ROOT) == null){
            //创建临时节点，防止创建节点过多
            client.create().creatingParentsIfNeeded().forPath(ZK_ROOT);
        }
        InterProcessMutex lock = new InterProcessMutex(client, getFullLockName());
        lock.acquire();
    }

    public boolean tryLock(long time, TimeUnit timeUnit) throws Exception {
        InterProcessMutex lock = new InterProcessMutex(client, getFullLockName());
        return lock.acquire(time, timeUnit);
    }

    public void unlock() throws Exception {
        InterProcessMutex lock = new InterProcessMutex(client, getFullLockName());
        lock.release();
        String path = ZK_ROOT + "/" + lockName;
        int size = client.getChildren().forPath(path).size();
        System.out.println(size);
        if (size == 0) {
            client.delete().forPath(path);
        }
    }

    public static void destory() {
        client.close();
    }
}